#include "Comm.hpp"

// 对应的程序在加载的时候,会自动构建全局变量,就要调用该类的构造函数 -- 创建管道文件
// 程序退出的时候,全局变量会被析构,自动调用析构函数,会自动删除管道文件
Init init;  // 管道文件只有在服务端创建即可

int main()
{
    // 1. 创建公共的key值
    key_t k = ftok(PATH_NAME, PROJ_ID);
    assert(k != -1);
    Log("create key done", Debug) << "server key: " << TransToHex(k) << endl;

    // 2. 创建共享内存(建议通信的发起者创建一个全新的共享内存)
    // 创建共享内存是也要指定权限
    int shmid = shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
    if(shmid == -1)
    {
        Log("create shm fail", Debug) << endl;
        exit(1);
    }
    Log("create shm done", Debug) << "shmid: " << shmid << endl;

    // 3. 建立页表映射(将共享内存挂接到当前进程地址空间)
    char* shmaddr = (char*)shmat(shmid, nullptr, 0);
    if(shmaddr == (char*)-1)
    {
        Log("attch shm fail", Debug) << "shmid: " << shmid << endl;
    }
    Log("attch shm done", Debug) << "shmid: " << shmid << endl;

    // 4. 进程通信
    // 可以将共享内存看成一个大的字符串
    // 注意：共享内存创建好全部都会被置成0

    // 服务端以读方式打开管道文件
    int fd = OpenFIFO(FIFO_NAME, READ);

    for(;;)
    {
        // 服务端等待客户端唤醒
        Wait(fd);

        printf("%s\n", shmaddr);
        if(strcmp(shmaddr, "quit") == 0) break;
        //sleep(1);
    }

    // 5. 将指定的共享内存从自己的进程空间中去关联
    int n = shmdt(shmaddr);
    assert(n != -1);
    (void)n;
    Log("detach shm done", Debug) << "shmid: " << shmid << endl; 

    // 6. 删除共享内存,IPC_RMID即便还有进程挂接该共享内存,依旧删除该共享内存
    n = shmctl(shmid, IPC_RMID, nullptr);
    assert(n != -1);
    (void)n;
    Log("delete shm done", Debug) << "shmid: " << shmid << endl;

    CloseFIFO(fd); 

    return 0;
}
